/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <hilog/log.h>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <stdint.h>
#include <string>

#include "../common/common.h"
#include "../manager/plugin_manager.h"
#include "geometry.h"
#include "plugin_render.h"
#include "render/Event.h"
#include <unistd.h>
#include <uv.h>
std::unordered_map<std::string, PluginRender *> PluginRender::m_instance;
OH_NativeXComponent_Callback PluginRender::m_callback;
OH_NativeXComponent_MouseEvent_Callback PluginRender::m_mouseCallback;

// 定义异步任务数据结构（可根据需求扩展）
struct AsyncData {
    std::string sampleid;
    std::string neuronname;
    std::string path;
    std::string color;
    std::shared_ptr<Geometry> neuron = nullptr;
    napi_env env;
    napi_callback_info info;
    PluginRender *render = nullptr;
};
void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB");
    if ((nullptr == component) || (nullptr == window)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceCreatedCB: component or window is null");
        return;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceCreatedCB: Unable to get XComponent id");
        return;
    }

    std::string id(idStr);
    auto render = PluginRender::GetInstance(id);
    uint64_t width;
    uint64_t height;
    int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
    if ((OH_NATIVEXCOMPONENT_RESULT_SUCCESS == xSize) && (nullptr != render)) {
        if (render->m_eglCore->EglContextInit(window, width, height)) {
//            render->m_eglCore->Background();
        }
    }
}

void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB");
    if ((nullptr == component) || (nullptr == window)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceChangedCB: component or window is null");
        return;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceChangedCB: Unable to get XComponent id");
        return;
    }

    std::string id(idStr);
    auto render = PluginRender::GetInstance(id);
    if (nullptr != render) {
        uint64_t width;
        uint64_t height;
        int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
        if ((OH_NATIVEXCOMPONENT_RESULT_SUCCESS == xSize) && (nullptr != render)) {
            if (render->m_eglCore->Resize(width, height)) {
                render->m_eglCore->Draw();
            }
        }
    }
}

void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB");
    if ((nullptr == component) || (nullptr == window)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceDestroyedCB: component or window is null");
        return;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "OnSurfaceDestroyedCB: Unable to get XComponent id");
        return;
    }

    std::string id(idStr);
    PluginRender::Release(id);
}

void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB");
    if ((nullptr == component) || (nullptr == window)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "DispatchTouchEventCB: component or window is null");
        return;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
                     "DispatchTouchEventCB: Unable to get XComponent id");
        return;
    }

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (nullptr != render) {
//        render->m_eglCore->Draw();
        render->OnTouchEvent(component, window);
    }
}

void DispatchMouseEventCB(OH_NativeXComponent *component, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB");
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    int32_t ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }

    std::string id(idStr);
    auto render = PluginRender::GetInstance(id);
    if (render != nullptr) {
        render->OnMouseEvent(component, window);
    }
}
void DispatchHoverEventCB(OH_NativeXComponent *component, bool isHover) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB");
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    int32_t ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }

    std::string id(idStr);
    auto render = PluginRender::GetInstance(id);
    if (render != nullptr) {
        render->OnHoverEvent(component, isHover);
    }
}

PluginRender::PluginRender(std::string &id) {
    this->m_id = id;
    this->m_eglCore = new EGLCore();
    OH_NativeXComponent_Callback *renderCallback = &PluginRender::m_callback;
    renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;
    renderCallback->OnSurfaceChanged = OnSurfaceChangedCB;
    renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
    renderCallback->DispatchTouchEvent = DispatchTouchEventCB;

    m_mouseCallback.DispatchMouseEvent = DispatchMouseEventCB;
    m_mouseCallback.DispatchHoverEvent = DispatchHoverEventCB;
    
//    OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &m_mouseCallback);
}

PluginRender *PluginRender::GetInstance(std::string &id) {
    if (m_instance.find(id) == m_instance.end()) {
        PluginRender *instance = new PluginRender(id);
        m_instance[id] = instance;
        return instance;
    } else {
        return m_instance[id];
    }
}

void PluginRender::Export(napi_env env, napi_value exports) {
    if ((nullptr == env) || (nullptr == exports)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: env or exports is null");
        return;
    }

    napi_property_descriptor desc[] = {
        {"setSpecies",nullptr,PluginRender::NapiSetSpecies,nullptr,nullptr,nullptr,napi_default,nullptr},
        {"draw", nullptr, PluginRender::NapiDraw, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"loadObj", nullptr, PluginRender::NapiLoadObj, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"removeNeuron", nullptr, PluginRender::NapiRemoveNeuron, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"addNeuron", nullptr, PluginRender::NapiAddNeuron, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"selectNeuron", nullptr, PluginRender::NapiSelectNeuron, nullptr, nullptr, nullptr, napi_default, nullptr}
    };

    if (napi_ok != napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed");
    }
}

napi_value PluginRender::NapiSetSpecies(napi_env env, napi_callback_info info){
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    size_t argc = 1;
    napi_value argv[1];
    if (napi_ok != napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: Unable to get XComponent id");
        return nullptr;
    }

    // 解析字符串参数
    char species[32] = {0};

    napi_get_value_string_utf8(env, argv[0], species, sizeof(species), nullptr);
    
    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {
        render->m_eglCore->SetSpecies(species);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->setSpecies executed");
    }
    return nullptr;
}


// NAPI registration method type napi_callback. If no value is returned, nullptr is returned.
napi_value PluginRender::NapiDraw(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: Unable to get XComponent id");
        return nullptr;
    }

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {
        render->m_eglCore->Draw();
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->Draw() executed");
    }
    return nullptr;
}

// NAPI registration method type napi_callback. If no value is returned, nullptr is returned.
napi_value PluginRender::NapiLoadObj(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: Unable to get XComponent id");
        return nullptr;
    }

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {
        render->m_eglCore->LoadObj("/data/storage/el2/base/haps/entry/files/997.obj");
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->LoadObj() executed");
    }
    return nullptr;
}
void ExecuteLoad(uv_work_t *work) {
    std::shared_ptr<SWCLoader> loader = std::make_shared<SWCLoader>();
    std::shared_ptr<Geometry> neuron;

    AsyncData *data = static_cast<AsyncData *>(work->data);
    try {
        // 执行加载操作（子线程）
        data->neuron = loader->load(data->path);
    } catch (const std::exception &e) {
        OH_LOG_ERROR(LOG_APP, "Load failed: %{public}s", e.what());
    }
}
void AfterLoad(uv_work_t *work, int status) {
    AsyncData *data = static_cast<AsyncData *>(work->data);
    napi_env env = data->env;
    napi_callback_info info = data->info;

    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return;
    }

    PluginRender *render = data->render;
    if (render) {
        render->m_eglCore->loaderCallback(data->neuron,data->color.c_str(), data->path.c_str());
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->addNeuron executed");
    }
    delete data;
    delete work;
    return;
}
void AfterRemove(uv_work_t*work, int status){
        AsyncData *data = static_cast<AsyncData *>(work->data);
    napi_env env = data->env;
    napi_callback_info info = data->info;

    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiAfterRemove");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiAfterRemove: env or info is null");
        return;
    }

    PluginRender *render = data->render;
    if (render) {
        render->m_eglCore->removeNeuron(data->sampleid.c_str(),data->neuronname.c_str(), data->path.c_str());
//        render->m_eglCore->Draw();
        
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->removeNeuron executed");
    }
    delete data;
    delete work;
    return;
}
void ExecuteRemove(uv_work_t* work){
    std::shared_ptr<SWCLoader> loader = std::make_shared<SWCLoader>();
    std::shared_ptr<Geometry> neuron;

    AsyncData *data = static_cast<AsyncData *>(work->data);
    try {

        // 执行加载操作（子线程）
        PluginRender *render = data->render;
        if (render) {
//            sleep(1.0);
//            render->m_eglCore->removeNeuron(data->sampleid.c_str(),data->neuronname.c_str(), data->path.c_str());
//            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->addNeuron executed");
        }
    } catch (const std::exception &e) {
        OH_LOG_ERROR(LOG_APP, "Load failed: %{public}s", e.what());
    }
}

napi_value PluginRender::NapiAddNeuron(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    size_t argc = 4;
    napi_value argv[4];
    if (napi_ok != napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: Unable to get XComponent id");
        return nullptr;
    }

    // 解析字符串参数
    char sampleid[32] = {0};
    char neuronname[32] = {0};
    char path[128] = {0};
    char color[32] = {0};
    napi_get_value_string_utf8(env, argv[0], sampleid, sizeof(sampleid), nullptr);
    napi_get_value_string_utf8(env, argv[1], neuronname, sizeof(neuronname), nullptr);
    napi_get_value_string_utf8(env, argv[2], color, sizeof(color), nullptr);
    napi_get_value_string_utf8(env, argv[3], path, sizeof(path), nullptr);

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {
        AsyncData *data = new AsyncData();
        data->env = env;
        data->info = info;
        data->path = path;
        data->color = color;
        data->render = render;

        uv_work_t *work = new uv_work_t;
        work->data = data;
        uv_loop_t *loop = nullptr;
        napi_get_uv_event_loop(env, &loop);
        int ret = uv_queue_work(loop, work, ExecuteLoad, AfterLoad);
        if (ret != 0) {
            OH_LOG_ERROR(LOG_APP, "uv_queue_work failed: %{public}d", ret);
            delete data;
            delete work;
            return nullptr;
        }

        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->addNeuron executed");
    }


    return nullptr;
}
napi_value PluginRender::NapiRemoveNeuron(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    size_t argc = 3;
    napi_value argv[3];
    if (napi_ok != napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: Unable to get XComponent id");
        return nullptr;
    }

    // 解析字符串参数
    char sampleid[32] = {0};
    char neuronname[32] = {0};
    char path[128] = {0};
    napi_get_value_string_utf8(env, argv[0], sampleid, sizeof(sampleid), nullptr);
    napi_get_value_string_utf8(env, argv[1], neuronname, sizeof(neuronname), nullptr);
    napi_get_value_string_utf8(env, argv[2], path, sizeof(path), nullptr);

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {

        render->m_eglCore->removeNeuron(sampleid, neuronname, path);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->removeNeuron executed");
    }
    return nullptr;
}

napi_value PluginRender::NapiSelectNeuron(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj");
    if ((nullptr == env) || (nullptr == info)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: env or info is null");
        return nullptr;
    }

    napi_value thisArg;
    size_t argc = 3;
    napi_value argv[3];
    if (napi_ok != napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_cb_info fail");
        return nullptr;
    }

    napi_value exportInstance;
    if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_get_named_property fail");
        return nullptr;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: napi_unwrap fail");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiLoadObj: Unable to get XComponent id");
        return nullptr;
    }

    // 解析字符串参数
    char sampleid[32] = {0};
    char neuronname[32] = {0};
    char path[128] = {0};
    napi_get_value_string_utf8(env, argv[0], sampleid, sizeof(sampleid), nullptr);
    napi_get_value_string_utf8(env, argv[1], neuronname, sizeof(neuronname), nullptr);
    napi_get_value_string_utf8(env, argv[2], path, sizeof(path), nullptr);

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);
    if (render) {

        render->m_eglCore->selectNeuron(sampleid, neuronname, path);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->removeNeuron executed");
    }
    return nullptr;
}

void PluginRender::Release(std::string &id) {
    PluginRender *render = PluginRender::GetInstance(id);
    if (nullptr != render) {
        render->m_eglCore->Release();
        delete render->m_eglCore;
        render->m_eglCore = nullptr;
        delete render;
        render = nullptr;
        m_instance.erase(m_instance.find(id));
    }
}

void PluginRender::OnTouchEvent(OH_NativeXComponent *nativeXComponent, void *window) {
    OH_NativeXComponent_TouchEvent touchEvent;
    OH_NativeXComponent_GetTouchEvent(nativeXComponent, window, &touchEvent);
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: Unable to get XComponent id");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender ", "OnTouchEvent position = %{public}f,%{public}f,touchCount= %{public}d",
                 touchEvent.x, touchEvent.y,touchEvent.numPoints);

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);

    auto event = std::make_shared<TouchEvent>();
    event->action = EventAction::NONE;
    event->x = touchEvent.x;
    event->y = touchEvent.y;
    event->pointCount = touchEvent.numPoints;
    for (int i=0;i<touchEvent.numPoints;i++){
        event->points[i].x( touchEvent.touchPoints[i].x);
        event->points[i].y( touchEvent.touchPoints[i].y);
    }
    switch (touchEvent.type) {
    case OH_NATIVEXCOMPONENT_DOWN: {
        event->action = EventAction::TOUCH_DOWN;
        break;
    }
    case OH_NATIVEXCOMPONENT_MOVE: {
        event->action = EventAction::TOUCH_MOVE;
        break;
    }
    case OH_NATIVEXCOMPONENT_UP: {
        event->action = EventAction::TOUCH_UP;
        break;
    }
    default:
        break;
    }
    render->m_eglCore->addEvent(event);
    render->m_eglCore->Draw();
}

void PluginRender::OnMouseEvent(OH_NativeXComponent *nativeXComponent, void *window) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnMouseEvent");
    OH_NativeXComponent_MouseEvent mouseEvent;
    int32_t ret = OH_NativeXComponent_GetMouseEvent(nativeXComponent, window, &mouseEvent);
    if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender",
                     "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d",
                     mouseEvent.x, mouseEvent.y, mouseEvent.action, mouseEvent.button);
    } else {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetMouseEvent error");
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDraw: Unable to get XComponent id");
    }

    std::string id(idStr);
    PluginRender *render = PluginRender::GetInstance(id);

    auto event = std::make_shared<MouseEvent>();
    event->action = EventAction::NONE;
    event->x = mouseEvent.x;
    event->y = mouseEvent.y;
    switch (mouseEvent.action) {
    case OH_NATIVEXCOMPONENT_MOUSE_PRESS: {
        event->action = EventAction::MOUSE_PRESS;
        break;
    }
    case OH_NATIVEXCOMPONENT_MOUSE_MOVE: {
        event->action = EventAction::MOUSE_MOVE;
        break;
    }
    case OH_NATIVEXCOMPONENT_MOUSE_RELEASE: {
        event->action = EventAction::MOUSE_RELEASE;
        break;
    }
    default:
        break;
    }
    switch (mouseEvent.button) {
    case OH_NATIVEXCOMPONENT_LEFT_BUTTON: {
        event->button = EventButton::LEFT;
        break;
    }
    case OH_NATIVEXCOMPONENT_RIGHT_BUTTON: {
        event->button = EventButton::RIGHT;
        break;
    }
    default:
        event->button = EventButton::NONE;

        break;
    }
    render->m_eglCore->addEvent(event);
    render->m_eglCore->Draw();
}

void PluginRender::OnHoverEvent(OH_NativeXComponent *component, bool isHover) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnHoverEvent isHover_ = %{public}d", isHover);
}